#python端代码
#python端使用mmap，在python端和Qt C++端实现共享内存通信，使用Windows系统信号量实现进程间同步
#pip install pywin32
#生成pyd文件命令，打包pyd时的python版本必须与运行时python版本一致
#python -m nuitka --module CommunicationClass.py
#或nuitka --module CommunicationClass_ori.py

import mmap
import os
import win32event
import win32api
import time

class CommunicationBase:
    def __init__(self, projectUUID):
        """
        Initializes the BasePredictor class.

        Args:
            projectUUID (str): projectUUID.
        """
        self.semaphoreSendName="semaphoreGet"+projectUUID
        self.semaphoreGetName="semaphoreSend"+projectUUID
        self.smSendName="smGet"+projectUUID
        self.smGetName="smSend"+projectUUID

        self.sm_SendMessage=mmap.mmap(-1, 1024, tagname=self.smSendName, access=mmap.ACCESS_WRITE)
        self.sm_GetMessage=mmap.mmap(-1, 1024, tagname=self.smGetName, access=mmap.ACCESS_WRITE)
        #sm_SendMessage=mmap.mmap(-1, 1024, tagname='my_share_mem', access=mmap.ACCESS_WRITE)
        #sm_GetMessage=mmap.mmap(-1, 1024, tagname='my_share_mem1', access=mmap.ACCESS_WRITE)
        
        self.semaphoreSend = win32event.CreateSemaphore(None, 1, 1, self.semaphoreSendName)  #用作进程间共享内存同步
        self.semaphoreGet = win32event.CreateSemaphore(None, 1, 1, self.semaphoreGetName)  #用作进程间共享内存同步
        #semaphoreSend = win32event.CreateSemaphore(None, 1, 1, "MySemaphore")  #用作进程间共享内存同步
        #semaphoreGet = win32event.CreateSemaphore(None, 1, 1, "MySemaphore1")  #用作进程间共享内存同步

    def sendMessage(self,msg):
        win32event.WaitForSingleObject(self.semaphoreSend,win32event.INFINITE)
        # 写之前先清空
        self.sm_SendMessage.seek(0)
        self.sm_SendMessage.write(bytes(self.sm_SendMessage.size()))
        sendmsg = msg
        self.sm_SendMessage.seek(0)
        self.sm_SendMessage.write(sendmsg.encode()); #只能写byte
        self.sm_SendMessage.flush()
        win32event.ReleaseSemaphore(self.semaphoreSend, 1)

    def getMessage(self):
        win32event.WaitForSingleObject(self.semaphoreGet,win32event.INFINITE)
        self.sm_GetMessage.seek(0)
        # sm_GetMessage.tell()
        getStr=self.sm_GetMessage.read().decode('utf8').replace('\x00','')
        self.sm_GetMessage.seek(0)
        #读完命令不清空，因为会多次读取
        # self.sm_GetMessage.write(bytes(self.sm_GetMessage.size()))
        win32event.ReleaseSemaphore(self.semaphoreGet, 1)
        # if getStr!='':
        #     i+=1
        #     if getStr not in list:
        #         print("错误数据:",getStr)
        return getStr

    def destroy(self):
        win32api.CloseHandle(self.semaphoreSend)
        win32api.CloseHandle(self.semaphoreGet)
        self.sm_SendMessage.close()
        self.sm_GetMessage.close()


# time.sleep(1)
if __name__ == '__main__':
    i=0
    com=CommunicationBase("uuid")
    print("开始")   
    while True:
        rst=com.getMessage()
        # print("循环")  
        time.sleep(0.01)
        if rst!='':
            if rst=="Stop":
                print("接收到退出命令！")
                break
        i=i+1
        com.sendMessage(str(i))
    com.sendMessage("Finish")
    com.destroy()
    print("结束")    


        
        
